package indi.lqzhi.basic.tools.bean;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;

import indi.lqzhi.basic.tools.lambda.function.Predicate;
import indi.lqzhi.basic.tools.lambda.function.Supplier;


/**
 * 对象池
 */
public enum BeanPool {
    ;

    /**
     * 单例池
     */
    private static final Cache<String,Object> pool = new Cache<>();


    /**
     * 伴随生命周期进行放入,可实现当生命周期结束时，自动移除对象
     * @param key   关键字
     * @param owner 生命周期观察者
     * @param object 需要存入的单例对象
     * @param <T> 泛型
     * @return 存入的值
     */
    @SuppressWarnings("unchecked")
    public static <T> T put(String key, LifecycleOwner owner,T object){
        //已经包含了，则只需要添加监听器
        owner.getLifecycle().addObserver((LifecycleEventObserver) (source, event) -> {
            if (event == Lifecycle.Event.ON_DESTROY){
                pool.remove(key);
            }
        });
        return (T) pool.put(key,object);//put数据返回
    }

    /**
     * 无伴随生命周期进行放入,该对象将一直存在与单例池中
     * @param key   关键字
     * @param object 需要存入的单例对象
     * @param <T> 泛型
     * @return 存入的值
     */
    @SuppressWarnings("unchecked")
    public static <T> T put(String key,T object){
        return (T) pool.put(key,object);
    }

    /**
     * 伴随生命周期进行放入,可实现当生命周期结束时，自动移除对象,默认key是object的全类名
     * @param owner 生命周期观察者
     * @param object 需要存入的单例对象
     * @param <T> 泛型
     * @return 存入的值
     */
    @SuppressWarnings("unchecked")
    public static <T> T put(LifecycleOwner owner,T object){
        String poolKey = object.getClass().getName();
        //已经包含了，则只需要添加监听器
        owner.getLifecycle().addObserver((LifecycleEventObserver) (source, event) -> {
            if (event == Lifecycle.Event.ON_DESTROY){
                pool.remove(poolKey);
            }
        });
        return (T) pool.put(poolKey,object);//put数据返回
    }

    /**
     * 无伴随生命周期进行放入,该对象将一直存在与单例池中,默认key是object的全类名
     * @param object 需要存入的单例对象
     * @param <T> 泛型
     * @return 存入的值
     */
    @SuppressWarnings("unchecked")
    public static <T> T put(T object){
        return (T) pool.put(object.getClass().getName(),object);
    }

    /**
     * 得到值
     * @param key 关键字
     * @param <T> 泛型
     * @return 值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(String key){
        return (T) pool.get(key);
    }

    /**
     * 得到值
     * @param classValue 类类型
     * @param <T> 泛型
     * @return 值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(Class<T> classValue){
        return (T) pool.get(classValue.getName());
    }

    /**
     * 得到值
     * @param classValue 类类型
     * @param defaultValue 默认值
     * @param <T> 泛型
     * @return 值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(Class<T> classValue,T defaultValue){
        return (T) pool.get(classValue.getName(),(Supplier<Object>) () -> defaultValue);
    }

    /**
     * 得到值
     * @param classValue 类类型
     * @param validPredicate 检查结果对象是否可用，如是否断开连接等
     * @param defaultValue 默认值
     * @param <T> 泛型
     * @return 值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(Class<T> classValue,Predicate<T> validPredicate, T defaultValue){
        return (T) pool.get(classValue.getName(), (Predicate<Object>) validPredicate,
                (Supplier<Object>) () -> defaultValue);
    }

    /**
     * 得到值
     * @param key 关键字
     * @param defaultValue 默认值
     * @param <T> 泛型
     * @return 值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(String key,T defaultValue){
        return (T) pool.get(key, (Supplier<Object>) () -> defaultValue);
    }

    /**
     * 得到值
     * @param key 关键字
     * @param validPredicate 检查结果对象是否可用，如是否断开连接等
     * @param defaultValue 默认值
     * @param <T> 泛型
     * @return 值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(String key, Predicate<T> validPredicate, T defaultValue){
        return (T) pool.get(key, (Predicate<Object>) validPredicate,
                (Supplier<Object>) () -> defaultValue);
    }



    /**
     * 移除指定Singleton对象
     *
     * @param clazz 类
     */
    public static void remove(Class<?> clazz) {
        if (null != clazz) {
            remove(clazz.getName());
        }
    }

    /**
     * 移除指定Singleton对象
     *
     * @param key 键
     */
    public static void remove(String key) {
        pool.remove(key);
    }


    /**
     * 判断是否存在Key
     * @param key key的值
     * @return true 存在 false 不存在
     */
    public static boolean existsKey(String key) {
        return pool.containsKey(key);
    }

    /**
     * 判断是否存在Key
     * @param classValue 类类型
     * @return true 存在 false 不存在
     */
    public static boolean existsKey(Class<?> classValue) {
        return pool.containsKey(classValue.getName());
    }

    /**
     * 判断是否存在value
     * @param value 判断的对象
     * @return true 存在 false 不存在
     */
    public static boolean existsValue(Object value) {
        return pool.containsValue(value);
    }


    /**
     * 清除所有Singleton对象
     */
    public static void destroy() {
        pool.clear();
    }
}
